package org.fast.develop.logicflow.springboot.configuration;

import org.fast.develop.logicflow.LogicFlowManagementConfiguration;
import org.fast.develop.logicflow.management.core.EventBus;
import org.fast.develop.logicflow.management.core.event.DeployedEvent;
import org.fast.develop.logicflow.management.service.LogicModelService;
import org.fast.develop.logicflow.management.service.LogicRepositoryService;
import org.fast.develop.logicflow.management.service.impl.ModelServiceImpl;
import org.fast.develop.logicflow.management.service.impl.RepositoryServiceImpl;
import org.fast.develop.logicflow.persistence.domain.LogicBytearrayRepositoryImpl;
import org.fast.develop.logicflow.persistence.domain.LogicDefinitionRepositoryImpl;
import org.fast.develop.logicflow.persistence.domain.LogicDeploymentRepositoryImpl;
import org.fast.develop.logicflow.persistence.domain.LogicModelRepositoryImpl;
import org.fast.develop.logicflow.persistence.jpa.repository.LogicBytearrayJpaRepository;
import org.fast.develop.logicflow.persistence.jpa.repository.LogicDefinitionJpaRepository;
import org.fast.develop.logicflow.persistence.jpa.repository.LogicDeploymentJpaRepository;
import org.fast.develop.logicflow.persistence.jpa.repository.LogicModelJpaRepository;
import org.fast.develop.logicflow.repository.domain.bytearray.LogicBytearrayRepository;
import org.fast.develop.logicflow.repository.domain.definition.LogicDefinitionRepository;
import org.fast.develop.logicflow.repository.domain.deployment.LogicDeploymentRepository;
import org.fast.develop.logicflow.repository.domain.model.LogicModelRepository;
import org.fast.develop.logicflow.rest.execute.LogicFlowExecutorEnhance;
import org.fast.develop.logicflow.runtime.LogicFlowRuntimeConfiguration;
import org.fast.develop.logicflow.runtime.LogicRuntimeService;
import org.fast.develop.logicflow.runtime.cache.IThreadStore;
import org.fast.develop.logicflow.runtime.cache.LogicDefinitionCache;
import org.fast.develop.logicflow.runtime.impl.LogicRuntimeServiceImpl;
import org.fast.develop.logicflow.runtime.repository.DefinitionRepositoryEnhance;
import org.fast.develop.logicflow.springboot.configuration.enhance.DefaultDefinitionRepositoryEnhance;
import org.fast.develop.logicflow.springboot.configuration.listener.ModelDeployedListener;
import org.fast.develop.logicflow.ws.LogicDebugService;
import org.fast.develop.logicflow.ws.LogicFlowServerEndpoint;
import org.fast.develop.logicflow.ws.manager.WsSessionManager;
import org.fast.develop.logicflow.ws.thread.ThreadExecuteManager;
import org.fast.develop.logicflow.ws.thread.ThreadStore;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author 莫寅
 * @createTime 2022-12-21 00:14
 * @desc：
 */
public class DefaultLogicFlowManagementConfiguration implements ApplicationContextAware, LogicFlowManagementConfiguration {


    private LogicBytearrayRepository logicBytearrayRepository;
    private LogicDefinitionRepository logicDefinitionRepository;
    private LogicDeploymentRepository logicDeploymentRepository;
    private LogicModelRepository logicModelRepository;

    private LogicModelService logicModelService;
    private LogicRepositoryService repositoryService;
    private LogicRuntimeService runtimeService;

    private LogicFlowRuntimeConfiguration logicFlowRuntimeConfiguration;

    private EventBus eventBus;
    private LogicDefinitionCache logicDefinitionCache;

    private LogicFlowServerEndpoint logicFlowServerEndpoint;

    private WsSessionManager wsSessionManager;

    private LogicDebugService logicDebugService;

    private LogicFlowExecutorEnhance logicFlowExecutorEnhance;

    private ThreadStore threadStore=new ThreadStore();

    private static ApplicationContext APPLICATION_CONTEXT;

    public DefaultLogicFlowManagementConfiguration(LogicFlowRuntimeConfiguration logicFlowRuntimeConfiguration,
                                                   LogicBytearrayJpaRepository logicBytearrayJpaRepository,
                                                   LogicDefinitionJpaRepository logicDefinitionJpaRepository,
                                                   LogicDeploymentJpaRepository logicDeploymentJpaRepository,
                                                   LogicModelJpaRepository logicModelJpaRepository) {
        init();
        initEventBus();

        this.logicFlowRuntimeConfiguration = logicFlowRuntimeConfiguration;


        this.logicBytearrayRepository = new LogicBytearrayRepositoryImpl(logicBytearrayJpaRepository);
        this.logicDefinitionRepository = new LogicDefinitionRepositoryImpl(logicDefinitionJpaRepository);
        this.logicDeploymentRepository = new LogicDeploymentRepositoryImpl(logicDeploymentJpaRepository);
        this.logicModelRepository = new LogicModelRepositoryImpl(logicModelJpaRepository);



        this.repositoryService = new RepositoryServiceImpl(logicDeploymentRepository, logicDefinitionRepository, logicModelRepository, logicBytearrayRepository, eventBus);
        this.logicModelService = new ModelServiceImpl(logicModelRepository, logicBytearrayRepository, repositoryService);


        DefinitionRepositoryEnhance definitionRepositoryEnhance = new DefaultDefinitionRepositoryEnhance(logicDefinitionRepository, logicBytearrayRepository);
        this.runtimeService = new LogicRuntimeServiceImpl(logicFlowRuntimeConfiguration, logicDefinitionCache, definitionRepositoryEnhance);
        logicFlowRuntimeConfiguration.setLogicRuntimeService(runtimeService);


        this.threadStore = new ThreadStore();
        ThreadExecuteManager threadExecuteManager = new ThreadExecuteManager(threadStore, this);
        this.logicDebugService = new LogicDebugService(threadExecuteManager);



        this.wsSessionManager = new WsSessionManager();
        this.logicFlowServerEndpoint = new LogicFlowServerEndpoint(this);


        this.logicFlowExecutorEnhance = new LogicFlowExecutorEnhance(logicFlowRuntimeConfiguration, logicModelService);
    }

    private void init(){
        LogicDefinitionCache logicDefinitionCache = new LogicDefinitionCache();
        this.logicDefinitionCache = logicDefinitionCache;
    }

    private void initEventBus(){
        EventBus eventBus = new EventBus();
        eventBus.register(DeployedEvent.class, new ModelDeployedListener(logicDefinitionCache));
        this.eventBus = eventBus;
    }

    public LogicBytearrayRepository getLogicBytearrayRepository() {
        return logicBytearrayRepository;
    }

    public LogicDefinitionRepository getLogicDefinitionRepository() {
        return logicDefinitionRepository;
    }

    public LogicDeploymentRepository getLogicDeploymentRepository() {
        return logicDeploymentRepository;
    }

    public LogicModelRepository getLogicModelRepository() {
        return logicModelRepository;
    }

    public LogicModelService getLogicModelService() {
        return logicModelService;
    }

    public LogicRepositoryService getRepositoryService() {
        return repositoryService;
    }

    public LogicRuntimeService getRuntimeService() {
        return runtimeService;
    }

    public LogicFlowRuntimeConfiguration getLogicFlowRuntimeConfiguration() {
        return logicFlowRuntimeConfiguration;
    }

    public LogicFlowServerEndpoint getLogicFlowServerEndpoint() {
        return logicFlowServerEndpoint;
    }

    public LogicFlowExecutorEnhance getLogicFlowExecutorEnhance() {
        return logicFlowExecutorEnhance;
    }

    public WsSessionManager getWsSessionManager() {
        return wsSessionManager;
    }

    public LogicDebugService getLogicDebugService() {
        return logicDebugService;
    }

    @Override
    public IThreadStore getThreadStore() {
        return threadStore;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.APPLICATION_CONTEXT = applicationContext;
    }


    public static ApplicationContext getApplicationContext() {
        return APPLICATION_CONTEXT;
    }


}
